/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.freedom.railhunter.main;

import org.freedom.railhunter.model.OrderConfiguration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import org.freedom.railhunter.exception.LoginFailedException;
import org.freedom.railhunter.exception.SessionExpiredException;
import org.freedom.railhunter.model.LeftTicketItem;
import org.freedom.railhunter.model.Passenger;
import org.freedom.railhunter.model.Order;
import org.freedom.railhunter.model.Purpose;
import org.freedom.railhunter.model.QueueCount;
import org.freedom.railhunter.model.SubmitOrderResult;
import org.freedom.railhunter.service.CookieService;
import org.freedom.railhunter.service.LoginService;
import org.freedom.railhunter.service.PassengerService;
import org.freedom.railhunter.service.RandCodeService;
import org.freedom.railhunter.service.TicketService;
import org.freedom.railhunter.util.UUWiseHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Alan
 */
public class Main {
    
    private static final Logger logger = LoggerFactory.getLogger(Main.class);
    
    private static final CookieService cookieService = CookieService.getInstance();
    
    private static final RandCodeService randCodeService = RandCodeService.getInstance();
    
    private static final LoginService loginService = LoginService.getInstance();
    
    private static final PassengerService passengerService = PassengerService.getInstance();
    
    private static final TicketService ticketService = TicketService.getInstance();
    
    private static Map<String, String> cookieData = cookieService.initCookie();
    
    public static void main(String[] args) throws Exception {
        OrderConfiguration configuration = OrderConfiguration.getInstance();
        configuration.loadOrderConfig(Thread.currentThread().getContextClassLoader()
                .getResource(OrderConfiguration.ORDER_CONFIG_FILE_NAME).getFile());
        
        try {
            // 登录到uu云
            UUWiseHelper.initAndLogin(configuration.getUuwiseUsername(), configuration.getUuwisePassword());
        } catch (Exception e) {
            logger.error("初始化及登录uu云失败！", e);
            return;
        }
        logger.info("成功初始化及登录uu云。");
        
        // 登录到12306
        randCodeService.buildRandCodeImageFile("login", cookieData);
        System.out.println("请输入验证码：");
        Scanner scanner = new Scanner(System.in);
        String code = scanner.nextLine();
        try {
            boolean loginResult = loginService.login(configuration.get12306UserName(), configuration.get12306Password(), code, cookieData);
            if (!loginResult) {
                logger.error("登录12306失败！");
                return;
            }
            logger.info("成功登录到12306。");
        } catch (LoginFailedException ex) {
            logger.error("登录12306失败！原因：" + ex.getMessage());
        }
        
        // 获取联系人
        Passenger[] normalPassengers = passengerService.getNoramlPassengers(cookieData);
        
        // 获取所有配置的乘车人
        List<Passenger> passengers = new ArrayList<>();
        for (String passengerName : configuration.getPassengers()) {
            for (Passenger passenger : normalPassengers) {
                if (passengerName.equals(passenger.getPassengerName())) {
                    passengers.add(passenger);
                    break;
                }
            }
        }
        
        cookieService.putJcSaveData(cookieData, configuration.getFromStation(), 
                configuration.getToStation(), configuration.getTrainDate());
        
        logger.info("暂停1秒。");
        Thread.sleep(1000);
        
        // 循环刷票
        logger.info("开始循环刷票：");
        boolean orderSuccess = false;
        while (!orderSuccess) {
            logger.info("查询...");
            LeftTicketItem[] leftTicketItems = ticketService.queryLeftTicket(configuration.getTrainDate(),
                    configuration.getFromStation().getTelecode(), configuration.getToStation().getTelecode(),
                    Purpose.ADULT.getCodes(), cookieData);
            logger.info("共查询到" + leftTicketItems.length + "车次。");

            final LinkedList leftTicketItemList = new LinkedList(Arrays.asList(leftTicketItems));
            Order order = ticketService.createOrder(leftTicketItemList, passengers, configuration.getTrainCodeList(), 
                    configuration.getSeatTypeList(), configuration.getTrainDate(), Purpose.ADULT.getCodes(), true);
            if (order == null) {
                logger.info("没有符合条件的车次，无法下单。");
                Thread.sleep(4950);
                continue;
            }
            
            logger.info("开始自动提交订单...");
            SubmitOrderResult submitResult;
            try {
                submitResult = ticketService.autoSubmitOrderRequest(order,
                        configuration.getFromStation().getName(), configuration.getToStation().getName(), cookieData);
                if (!submitResult.isSubmitStatus()) {
                    logger.info("提交订单失败。");
                    Thread.sleep(4900);
                    continue;
                }
            } catch (SessionExpiredException ex) {
                // 重新登录
                logger.info("Session失效，需要重新登录！");
                Thread.sleep(4900);
                loginService.logout(cookieData);
                cookieData = cookieService.initCookie();
                try {
                    loginService.login(code, code, code, cookieData);
                } catch (LoginFailedException ex1) {
                    logger.error("登录12306失败！原因：" + ex.getMessage());
                }
                continue;
            }
            
            logger.info("成功提交订单，开始查询队列余票数量...");
            QueueCount queueCount;
            try {
                queueCount = ticketService.getQueueCountAsync(order, submitResult, cookieData);
            } catch (SessionExpiredException ex) {
                logger.info("Session失效，需要重新登录！");
                Thread.sleep(4900);
                // 重新登录
                loginService.logout(cookieData);
                cookieData = cookieService.initCookie();
                try {
                    loginService.login(code, code, code, cookieData);
                } catch (LoginFailedException ex1) {
                    logger.error("登录12306失败！原因：" + ex.getMessage());
                }
                continue;
            }
            
            if (queueCount.isQueueMoreThanRemaining()
                    || queueCount.getCountT() >= queueCount.getRemainingCount()
                    || queueCount.getRemainingCount() < passengers.size()) {
                // 余票不足时将当前车次排到最后（优先级最低），优化自动选择的成功率
                LeftTicketItem selectedItem = order.getLeftTicketItem();
                leftTicketItemList.remove(selectedItem);
                leftTicketItemList.addLast(selectedItem);
                logger.info("对不起，余票不足！");
                continue;
            }
            
            logger.info("还有余票，开始获取验证码...");
            byte[] img = randCodeService.buildRandCodeImageBytes(cookieData);
            // 自动识别验证码
            String rcode = UUWiseHelper.recognizeRandCode(img);
            logger.info("成功识别验证码，开始确认订单...");
            // 确认订单
            boolean confirm = ticketService.confirmSingleForQueueAsys(order, submitResult, rcode, cookieData);
            if (!confirm) {
                logger.info("订票确认失败。");
            } else {
                orderSuccess = true;
                logger.info("恭喜您！订票成功！");
            }
        }
    }
}
